﻿using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using ESRI.ArcGIS.Client.FeatureService;

namespace ESRI.ArcGIS.Client.Async
{
    public static partial class FeatureLayerExtensions
    {
        #region AddAttachmentTaskAsync

        /// <summary>
        /// Adds an attachment to a feature.
        /// </summary>
        /// <param name="featureLayer"></param>
        /// <param name="g">The feature to add an attachment to.</param>
        /// <param name="file">The file stream used for the attachment.</param>
        /// <param name="filename">Name of the attachment.</param>
        /// <returns></returns>
        public static Task<AttachmentResult> AddAttachmentTaskAsync(this FeatureLayer featureLayer, Graphic g, Stream file,
            string filename)
        {
            var tcs = new TaskCompletionSource<AttachmentResult>();
            featureLayer.AddAttachment(g, file, filename, tcs.SetResult, tcs.SetException);
            return tcs.Task;
        }

        /// <summary>
        /// Adds an attachment to a feature.
        /// </summary>
        /// <param name="featureLayer"></param>
        /// <param name="g">The feature to add an attachment to.</param>
        /// <param name="file">The file stream used for the attachment.</param>
        /// <param name="filename">Name of the attachment.</param>
        /// <param name="contentType">MimeType of the content.</param>
        /// <returns></returns>
        public static Task<AttachmentResult> AddAttachmentTaskAsync(this FeatureLayer featureLayer, Graphic g, Stream file,
            string filename, string contentType)
        {
            var tcs = new TaskCompletionSource<AttachmentResult>();
            featureLayer.AddAttachment(g, file, filename, contentType, tcs.SetResult, tcs.SetException);
            return tcs.Task;
        }

        /// <summary>
        /// Adds an attachment to a feature.
        /// </summary>
        /// <param name="featureLayer"></param>
        /// <param name="featureID">The ID of the feature to add an attachment to.</param>
        /// <param name="file">The file stream used for the attachment.</param>
        /// <param name="filename">Name of the attachment.</param>
        /// <returns></returns>
        public static Task<AttachmentResult> AddAttachmentTaskAsync(this FeatureLayer featureLayer, string featureID, Stream file,
            string filename)
        {
            var tcs = new TaskCompletionSource<AttachmentResult>();
            featureLayer.AddAttachment(featureID, file, filename, tcs.SetResult, tcs.SetException);
            return tcs.Task;
        }

        /// <summary>
        /// Adds an attachment to a feature.
        /// </summary>
        /// <param name="featureLayer"></param>
        /// <param name="featureID">The ID of the feature to add an attachment to.</param>
        /// <param name="file">The file stream used for the attachment.</param>
        /// <param name="filename">Name of the attachment.</param>
        /// <param name="contentType">MimeType of the content.</param>
        /// <returns></returns>
        public static Task<AttachmentResult> AddAttachmentTaskAsync(this FeatureLayer featureLayer, string featureID, Stream file,
            string filename, string contentType)
        {
            var tcs = new TaskCompletionSource<AttachmentResult>();
            featureLayer.AddAttachment(featureID, file, filename, contentType, tcs.SetResult, tcs.SetException);
            return tcs.Task;
        }

        #endregion

        #region DeleteAttachmentTaskAsync

        /// <summary>
        /// Deletes one or more attachments.
        /// </summary>
        /// <param name="featureLayer"></param>
        /// <param name="g">The graphic to delete attachments from.</param>
        /// <param name="attachmentIds">The attachment ids.</param>
        /// <returns></returns>
        public static Task<AttachmentResult[]> DeleteAttachmentTaskAsync(this FeatureLayer featureLayer, Graphic g,
            string[] attachmentIds)
        {
            var tcs = new TaskCompletionSource<AttachmentResult[]>();
            featureLayer.DeleteAttachment(g, attachmentIds, tcs.SetResult, tcs.SetException);
            return tcs.Task;
        }

        /// <summary>
        /// Deletes one or more attachments.
        /// </summary>
        /// <param name="featureLayer"></param>
        /// <param name="featureID">The ID of the feature to delete attachments from.</param>
        /// <param name="attachmentIds">The attachment ids.</param>
        /// <returns></returns>
        public static Task<AttachmentResult[]> DeleteAttachmentTaskAsync(this FeatureLayer featureLayer,
            string featureID, string[] attachmentIds)
        {
            var tcs = new TaskCompletionSource<AttachmentResult[]>();
            featureLayer.DeleteAttachment(featureID, attachmentIds, tcs.SetResult, tcs.SetException);
            return tcs.Task;
        }

        #endregion

        #region QueryAttachmentInfosTaskAsync

        /// <summary>
        /// Queries for a list of attachments for a specific graphic.
        /// </summary>
        /// <param name="featureLayer"></param>
        /// <param name="g">The graphic to query attachment info for.</param>
        /// <returns></returns>
        public static Task<IEnumerable<AttachmentInfo>> QueryAttachmentInfosTaskAsync(this FeatureLayer featureLayer,
            Graphic g)
        {
            var tcs = new TaskCompletionSource<IEnumerable<AttachmentInfo>>();
            featureLayer.QueryAttachmentInfos(g, tcs.SetResult, tcs.SetException);
            return tcs.Task;
        }

        /// <summary>
        /// Queries for a list of attachments for a feature with the specified feature ID.
        /// </summary>
        /// <param name="featureLayer"></param>
        /// <param name="featureID">The feature ID to query for.</param>
        /// <returns></returns>
        public static Task<IEnumerable<AttachmentInfo>> QueryAttachmentInfosTaskAsync(this FeatureLayer featureLayer,
            string featureID)
        {
            var tcs = new TaskCompletionSource<IEnumerable<AttachmentInfo>>();
            featureLayer.QueryAttachmentInfos(featureID, tcs.SetResult, tcs.SetException);
            return tcs.Task;
        }

        #endregion

        // TODO: SaveEdits
        //public static Task SaveEditsTaskAsync(this FeatureLayer featureLayer)
        //{
        //    if (featureLayer == null) throw new ArgumentNullException("featureLayer");
        //    if (!featureLayer.HasEdits)
        //    {
        //        // TODO: return empty results
        //    }
        //    // TODO: BeginSaveEdits can cancel operation 

        //    // TODO: SaveEdits can just return
            
        //    // TODO: EndSaveEdits raises after UpdateFailed?
        //    featureLayer.SaveEdits();
        //}

        // TODO: CancelEditsTaskAsync

        // TODO: UpdateTaskAsync
    }
}